// 保存Vue
let _Vue = null

export default class VueRouter {
  // 作为vue插件需求的静态方法
  static install(Vue) {
    // 判断当前插件是否已安装
    if (VueRouter.install.installed) return
    VueRouter.install.installed = true
    // 将Vue保存到全局变量
    _Vue = Vue
    // 将router对象注入Vue实例
    _Vue.mixin({
      beforeCreate() {
        if (!this.$options.router) return
        _Vue.prototype.$router = this.$options.router
      }
    })
  }

  constructor(options) {
    this.options = options
    this.routeMap = {}
    this.data = _Vue.observable({ current: '/' })
    this.init()
  }

  init() {
    // 遍历所有路由规则，解析成键值对的形式存储
    this.options.routes.forEach(route => this.routeMap[route.path] = route.component)
    // 初始化注册 router-link 组件
    this.initComponent(_Vue)
    // 注册锚点变化的监听事件
    this.initEvent()
  }

  initComponent(Vue) {
    Vue.component('router-link', {
      render: function (h) {
        return h('a', {
          // 由于要实现的是hash模式，因此路由地址需要拼接在锚点后
          // 所以在 href 传入路由地址时，手动拼接上 #
          attrs: { href: `#${this.to}` }
        }, [this.$slots.default])
      },
      props: {
        to: {
          type: String,
          required: true
        }
      }
    })

    const self = this
    Vue.component('router-view', {
      render: function(h) {
        const component = self.routeMap[self.data.current]
        return h(component)
      }
    })
  }

  initEvent() {
    window.onhashchange = e => {
      const { newURL } = e
      // 截取锚点后面的路由地址
      const path = newURL.split('#')[1]
      // 将路由地址赋值给current, 触发组件更新
      this.data.current = path
    }
  }
}